#include <string>
#include <vector>
#include <iostream>

#ifndef __DIR_H
#define __DIR_H

class INamed {
public:
  virtual const std::string& Name() const = 0;
};

class CHasName : public INamed {
protected:
  std::string name;

public:
  CHasName(const std::string &_name) : name(_name) { }
  virtual const std::string& Name() const { return name; }
};

class IEntry {

public:
  IEntry() { }
  virtual ~IEntry() { };
//  virtual bool IsFile() const { return false; }
//  virtual bool IsDir() const { return false; }
};

class IFile : public IEntry {
public:
//  virtual bool IsFile() const { return true; }

//  typedef std::vector<std::string>::iterator lines_iterator;
  
//  virtual lines_iterator begin() = 0;
//  virtual lines_iterator end() = 0;
//  virtual void read_block(void *_buffer, size_t _size, size_t _start = 0) = 0;
  virtual void* read() = 0;
  virtual size_t size() = 0;
  virtual void free() = 0;
};

class ITextFile : public IEntry {
public:
  typedef std::vector<std::string>::iterator lines_iterator;

  virtual lines_iterator begin() = 0;
  virtual lines_iterator end() = 0;
};

class CTextFile : public ITextFile, public CHasName {
protected:
  std::vector<std::string> vl;

public:
  CTextFile(const std::string &_name) : CHasName(_name) {
    //std::cerr << "CFile::CFile" << std::endl;
    read();
  }
  virtual void read();
  virtual void free() { vl.clear(); }

public:
  virtual lines_iterator begin() { return vl.begin(); }
  virtual lines_iterator end() { return vl.end(); }
};

class CFile : public IFile, public CHasName {
  void *pdata;
  size_t sz;

  void* read_from_disk();

public:
  CFile(const std::string &_name) : CHasName(_name), pdata(NULL), sz(0) {
    //std::cerr << "CFile::CFile" << std::endl;
    read();
  }

public:
//  virtual lines_iterator begin() { return vl.begin(); }
//  virtual lines_iterator end() { return vl.end(); }
  virtual void* read() {
    if (NULL == pdata) {
      void *p = read_from_disk();
      pdata = p;
      return p;
    }
    //read_from_disk();
    return pdata;
  }

  virtual void free() { 
    if (NULL != pdata) {
      delete[] (char*)pdata;
      pdata = NULL;
    }
  }
  
  virtual size_t size() {
    return sz;
  }
};

class IDir : public IEntry {
public:
  
  typedef std::vector<IEntry*>::iterator iterator;

  virtual iterator begin() = 0;
  virtual iterator end() = 0;

  virtual bool IsDir() const { return true; }
};

class CDir : public IDir, public CHasName { 
protected:

  std::vector<IEntry*> ve;
  bool bInitialized;
  
public:
  virtual void refresh();

public:
  CDir(const std::string &_name) : CHasName(_name), bInitialized(false) {
    std::cerr << "CDir[" << Name() << "]::CDir" << std::endl;
//    if (Name().substr(Name().size() - 1, 1) != "." && Name().substr(Name().size() - 2, 2) != "..") refresh();
  }

  typedef std::vector<IEntry*>::iterator iterator;

  virtual iterator begin() { 
    if (!bInitialized 
        && Name().substr(Name().size() - 1, 1) != "." 
        && Name().substr(Name().size() - 2, 2) != "..") {
      refresh();
      bInitialized = true;
    }

    return ve.begin();
  }
  virtual iterator end() { return ve.end(); }
};

class IEntryFactory {
public:

  virtual IEntry* Create(const std::string &name) const = 0;
};

class CFSEntryFactory : public IEntryFactory {
public:

  virtual IEntry* Create(const std::string &name) const; 
};

extern CFSEntryFactory filesystem;

#endif
